home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / Snippets / Devices / SCSI Simple Sample / Src / SCSISimpleSampleMain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-24  |  16.1 KB  |  700 lines  |  [TEXT/KAHL]

  1. /*                                SCSIScanBusMain.c                                */
  2. /*
  3.  * SCSIScanBusMain.c
  4.  * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
  5.  * This is a fairly general, and very limited, application framework.
  6.  * Mostly, you take this, the Log Manager, and the Window Utilities and paste
  7.  * in the application-specific menu handling.
  8.  */
  9. #define EXTERN
  10. #include    "SCSISimpleSample.h"
  11. #include    <Packages.h>
  12. #include    <Desk.h>
  13. #include    <OSEvents.h>
  14. #pragma segment MainCode
  15.  
  16. #ifdef __powerc
  17. /*
  18.  * Power PC does not automatically define the QuickDraw globals. This is because
  19.  * only "application" code-fragments need these globals, and this cannot be
  20.  * determined before the code fragment is constructed.
  21.  */
  22. QDGlobals            qd;        /* This is not automatically defined on PowerPC        */
  23. #endif
  24.  
  25. void                                main(void);
  26. void                                EventLoop(void);
  27. void                                DoMouseEvent(void);
  28. void                                DoContentClick(
  29.         WindowPtr                        theWindow
  30.     );
  31. void                                DoCommand(
  32.         WindowPtr                        theWindow,
  33.         long                            menuChoice
  34.     );
  35. void                                DoWindowKeyDown(
  36.         WindowPtr                        theWindow
  37.     );
  38. void                                SetupEverything(void);
  39. void                                AdjustMenus(void);
  40. void                                AdjustEditMenu(
  41.         Boolean                            isDeskAccessory
  42.     );
  43. void                                SetupMenus(void);
  44. void                                BuildWindow(void);
  45. void                                DecorateDisplay(
  46.         WindowPtr                        theWindow,
  47.         Boolean                            redraw
  48.     );
  49. void                                DrawWindow(
  50.         WindowPtr                        theWindow
  51.     );
  52. void                                DoAbout(void);
  53. void                                DoPageSetup(void);
  54. void                                HexToString(
  55.         unsigned long                    value,
  56.         short                            hexDigits,
  57.         Str255                            result
  58.     );
  59. Boolean                                HexToNum(
  60.         ConstStr255Param                hexString,
  61.         unsigned long                    *result
  62.     );
  63.         
  64. #define IsOurWindow(theWindow)    ((theWindow) == gMainWindow)
  65. /*
  66.  * This preserves the currently-chosen host bus ID in case the user switches
  67.  * between "old" and "new" SCSI Managers.
  68.  */
  69. static unsigned short                gOldHostBusID;
  70.  
  71. void
  72. main(void)
  73. {
  74.         SetupEverything();
  75.         BuildWindow();
  76.         gUpdateMenusNeeded = TRUE;
  77.         gInForeground = TRUE;
  78.         if ((gEnableNewSCSIManager = AsyncSCSIPresent()))
  79.             LOG("\pHas asynchronous SCSI Manager");
  80.         else {
  81.             LOG("\pAsynchronous SCSI Manager not present");
  82.         }
  83.         gEnableSelectWithATN = gEnableNewSCSIManager;
  84.         InitCursor();
  85.         while (gQuitNow == FALSE) {
  86.             EventLoop();
  87.         }
  88.         ExitToShell();
  89. }
  90.  
  91. /*
  92.  * BuildWindow creates a document window and stores a text log
  93.  * as its content.
  94.  */
  95. void
  96. BuildWindow()
  97. {
  98.         short                    fontSize;
  99.         short                    fontNumber;
  100.         Rect                    viewRect;
  101.         
  102.         fontSize = 10;
  103.         GetFNum("\pCourier", &fontNumber);
  104.         if (RealFont(fontNumber, fontSize) == FALSE)
  105.             fontNumber = applFont;
  106.         viewRect = qd.screenBits.bounds;
  107.         viewRect.top += (GetMBarHeight() * 2);
  108.         viewRect.bottom -= 4;
  109.         viewRect.left += 4;
  110.         viewRect.right = (width(viewRect) / 2);
  111.         gMainWindow = NewWindow(
  112.                         NULL,
  113.                         &viewRect,
  114.                         "\pSCSI Scan Bus Sample",
  115.                         TRUE,
  116.                         zoomDocProc,
  117.                         (WindowPtr) -1L,
  118.                         TRUE,                /* Has GoAway box        */
  119.                         0                    /* No refCon            */
  120.                     );
  121.         if (gMainWindow == NULL) {
  122.             SysBeep(10);
  123.             ExitToShell();
  124.         }
  125.         SetPort(gMainWindow);
  126.         viewRect = gMainWindow->portRect;
  127.         viewRect.right -= kScrollBarOffset;
  128.         viewRect.bottom -= kScrollBarOffset;
  129.         gLogListHandle = CreateLog(
  130.                     &viewRect,
  131.                     fontNumber,
  132.                     fontSize,
  133.                     kLogLines
  134.                 );
  135.         if (gLogListHandle == NULL) {
  136.             SysBeep(10);
  137.             ExitToShell();
  138.         }
  139. }
  140.  
  141. void
  142. EventLoop(void)
  143. {
  144.         long                            menuChoice;
  145.         register WindowPtr                theWindow;
  146.         GrafPtr                            savePort;
  147.         Boolean                            isActivating;
  148.         
  149.         if (gUpdateMenusNeeded) {
  150.             gUpdateMenusNeeded = FALSE;
  151.             AdjustMenus();
  152.         }
  153.         WaitNextEvent(
  154.             everyEvent,
  155.             &EVENT,
  156.             (gInForeground) ? 10L : 60L,
  157.             NULL
  158.         );
  159.         theWindow = FrontWindow();
  160.         switch (EVENT.what) {
  161.         case nullEvent:
  162.             break;
  163.         case keyDown:
  164.         case autoKey:
  165.             if ((EVENT.message & charCodeMask) == '.'
  166.              && (EVENT.modifiers & cmdKey) != 0) {
  167.                 FlushEvents(keyDown | autoKey, 0);
  168.                 gQuitNow = TRUE;
  169.             }
  170.             else if ((EVENT.modifiers & cmdKey) != 0) {
  171.                 if (EVENT.what == keyDown) {
  172.                     menuChoice = MenuKey(EVENT.message & charCodeMask);
  173.                     if (HiWord(menuChoice) != 0)
  174.                         DoCommand(theWindow, menuChoice);
  175.                     else if (IsOurWindow(theWindow)) {
  176.                         DoWindowKeyDown(theWindow);
  177.                     }
  178.                 }
  179.             }
  180.             else if (IsOurWindow(theWindow)) {
  181.                 DoWindowKeyDown(theWindow);
  182.             }
  183.             break;
  184.         case mouseDown:
  185.             DoMouseEvent();
  186.             break;
  187.         case updateEvt:
  188.             theWindow = (WindowPtr) EVENT.message;
  189.             GetPort(&savePort);
  190.             SetPort(theWindow);
  191.             BeginUpdate(theWindow);
  192.             EraseRect(&theWindow->portRect);
  193.             DrawControls(theWindow);
  194.             DrawGrowIcon(theWindow);
  195.             if (IsOurWindow(theWindow))
  196.                 DrawWindow(theWindow);
  197.             EndUpdate(theWindow);
  198.             SetPort(savePort);
  199.             break;
  200.         case activateEvt:
  201.             theWindow = (WindowPtr) EVENT.message;
  202.             isActivating = ((EVENT.modifiers & activeFlag) != 0);
  203.             goto activateEvent;
  204.             break;
  205.         case osEvt:
  206.             switch (((unsigned long) EVENT.message) >> 24) {
  207.             case mouseMovedMessage:
  208.                 break;
  209.             case suspendResumeMessage:
  210.                 isActivating = ((EVENT.message & 0x01) != 0);
  211. activateEvent:        if (isActivating) {
  212.                     /*
  213.                      * Activate this window. Activate events define theWindow
  214.                      * from the event record, while suspend/resume uses the
  215.                      * pre-set FrontWindow value.
  216.                      */
  217.                     SelectWindow(theWindow);
  218.                     (void) TEFromScrap();
  219.                 }
  220.                 if (IsOurWindow(theWindow) && gLogListHandle != NULL)
  221.                     LActivate(isActivating, gLogListHandle);
  222.                 else {
  223.                     /* Desk accessory or what? */
  224.                 }
  225.                 gInForeground = isActivating;
  226.                 gUpdateMenusNeeded = TRUE;
  227.                 break;
  228.             }
  229.             break;
  230.         }
  231. }
  232.  
  233. /*
  234.  * DoMouseEvent
  235.  * The user clicked on something. Handle application-wide processing here, or call
  236.  * a Catalog Browser function for specific action.
  237.  */
  238. void
  239. DoMouseEvent(void)
  240. {
  241.         WindowPtr        theWindow;
  242.         short            whichPart;
  243.         
  244.         whichPart = FindWindow(EVENT.where, &theWindow);
  245.         if (theWindow == NULL)
  246.             theWindow = FrontWindow();
  247.         if (whichPart == inMenuBar && IsOurWindow(theWindow) == FALSE)
  248.             theWindow = FrontWindow();
  249.         switch (whichPart) {
  250.         case inDesk:
  251.             break;
  252.         case inMenuBar:
  253.             InitCursor();
  254.             DoCommand(theWindow, MenuSelect(EVENT.where));
  255.             break;
  256.         case inDrag:
  257.             DragWindow(theWindow, EVENT.where, &qd.screenBits.bounds);
  258.             break;
  259.         case inGoAway:
  260.             if (TrackGoAway(theWindow, EVENT.where)) {
  261.                 if (IsOurWindow(theWindow)) {
  262.                     /*
  263.                      * Not quite so simple: we need to handle open files, too.
  264.                      */
  265.                     gQuitNow = TRUE;
  266.                 }
  267.             }
  268.             break;
  269.         case inZoomIn:
  270.         case inZoomOut:
  271.             if (IsOurWindow(theWindow)
  272.              && TrackBox(theWindow, EVENT.where, whichPart)) {
  273.                 DoZoomWindow(theWindow, whichPart);
  274.                 goto resizeWindow;
  275.             }
  276.             break;
  277.         case inGrow:
  278.             if (IsOurWindow(theWindow)) {
  279.                 if (DoGrowWindow(
  280.                             theWindow,
  281.                             EVENT.where,
  282.                             kMinWindowWidth,
  283.                             kMinWindowHeight
  284.                         )) {
  285. resizeWindow:        DecorateDisplay(theWindow, TRUE);
  286.                 }
  287.             }
  288.             break;
  289.         case inContent:
  290.             if (theWindow != FrontWindow())
  291.                 SelectWindow(theWindow);
  292.             else if (IsOurWindow(theWindow)) {
  293.                 DoContentClick(theWindow);
  294.             }
  295.             else {
  296.                 /* Nothing happens here        */
  297.             }
  298.             break;
  299.         default:
  300.             break;
  301.         }
  302.         /*
  303.          * Do not touch theWindow here.
  304.          */
  305. }
  306.  
  307. void
  308. DoContentClick(
  309.         WindowPtr                theWindow
  310.     )
  311. {
  312. #pragma unused (theWindow)
  313.         DoClickInLog(gLogListHandle, &EVENT);
  314. }
  315.  
  316. void
  317. DoWindowKeyDown(
  318.         WindowPtr                        theWindow
  319.     )
  320. {
  321. #pragma unused (theWindow)
  322.         /* Nothing happens here */
  323. }
  324.  
  325. void
  326. DrawWindow(
  327.         WindowPtr                        theWindow
  328.     )
  329. {
  330. #pragma unused (theWindow)
  331.         UpdateLog(gLogListHandle);
  332. }
  333.  
  334. void
  335. DecorateDisplay(
  336.         WindowPtr                        theWindow,
  337.         Boolean                            redraw
  338.     )
  339. {
  340. #pragma unused (redraw)
  341.         Rect                            viewRect;
  342.         
  343.         viewRect = theWindow->portRect;
  344.         viewRect.right -= kScrollBarOffset;
  345.         viewRect.bottom -= kScrollBarOffset;
  346.         if (gLogListHandle != NULL) {
  347.             MoveLog(gLogListHandle, viewRect.left, viewRect.top);
  348.             SizeLog(gLogListHandle, width(viewRect), height(viewRect));
  349.         }
  350. }
  351.  
  352. void
  353. DoCommand(
  354.         WindowPtr                        theWindow,
  355.         long                            menuChoice
  356.     )
  357. {
  358.         short                            menuItem;
  359.         Str255                            menuText;
  360.         GrafPtr                            savePort;
  361.         OSErr                            status;
  362.  
  363.         menuItem = LoWord(menuChoice);
  364.         switch (HiWord(menuChoice)) {
  365.         case MENU_Apple:
  366.             if (menuItem == kAppleAbout)
  367.                 DoAbout();
  368.             else {
  369.                 GetItem(gAppleMenu, menuItem, menuText);
  370.                 AdjustEditMenu(TRUE);
  371.                 GetPort(&savePort);
  372.                 OpenDeskAcc(menuText);
  373.                 SetPort(savePort);
  374.                 AdjustEditMenu(IsOurWindow(theWindow) == FALSE);
  375.             }
  376.             break;
  377.         case MENU_File:
  378.             switch (menuItem) {
  379.             case kFileCreateLogFile:
  380.                 status = SaveLogFile(
  381.                             gLogListHandle,
  382.                             "\pSave Log",
  383.                             "\pSCSI Test Log",
  384.                             'ttxt'
  385.                         );
  386.                 break;
  387.             case kFileCloseLogFile:
  388.                 status = CloseLogFile(gLogListHandle);
  389.                 break;
  390.             case kFilePageSetup:
  391.                 DoPageSetup();
  392.                 break;
  393.             case kFilePrint:
  394.                 PrintLog(gLogListHandle, gPrintHandle);
  395.                 break;
  396.             case kFileDebug:
  397.                 Debugger();
  398.                 break;
  399.             case kFileQuit:
  400.                 gQuitNow = TRUE;
  401.                 break;
  402.             }
  403.             break;
  404.         case MENU_Test:
  405.             switch (menuItem) {
  406.             case kTestEnableNewManager:
  407.                 /*
  408.                  * Note that this menu option is disabled if the asynchronous
  409.                  * SCSI Manager is not present. This means that, if it is
  410.                  * not present at application start, it can't be enabled later.
  411.                  */
  412.                 gEnableNewSCSIManager = (!gEnableNewSCSIManager);
  413.                 if (gEnableNewSCSIManager)
  414.                     gCurrentDevice.bus = gOldHostBusID;
  415.                 else {
  416.                     gOldHostBusID = gCurrentDevice.bus;
  417.                     gCurrentDevice.bus = 0;
  418.                 }
  419.                 gUpdateMenusNeeded = TRUE;
  420.                 break;
  421.             case kTestEnableAllLogicalUnits:
  422.                 /*
  423.                  * The ROM SCSI Manager on the Quadra 660-AV and 840-AV has
  424.                  * a bug that will hang the machine if it tries to access
  425.                  * a non-zero logical unit. This menu option makes that error
  426.                  * harder to elicit.
  427.                  */
  428.                 gMaxLogicalUnit = (gMaxLogicalUnit == 0) ? 7 : 0;
  429.                 if (gCurrentDevice.LUN > gMaxLogicalUnit)
  430.                     gCurrentDevice.LUN = gMaxLogicalUnit;
  431.                 gUpdateMenusNeeded = TRUE;
  432.                 break;
  433.             case kTestEnableSelectWithATN:
  434.                 gEnableSelectWithATN = !gEnableSelectWithATN;
  435.                 gUpdateMenusNeeded = TRUE;
  436.                 break;
  437.             case kTestDoDisconnect:
  438.                 gDoDisconnect = !gDoDisconnect;
  439.                 gUpdateMenusNeeded = TRUE;
  440.                 break;
  441.             case kTestDontDisconnect:
  442.                 gDontDisconnect = !gDontDisconnect;
  443.                 gUpdateMenusNeeded = TRUE;
  444.                 break;
  445.             case kTestVerboseDisplay:
  446.                 gVerboseDisplay = (!gVerboseDisplay);
  447.                 gUpdateMenusNeeded = TRUE;
  448.                 break;
  449.             case kTestListSCSIDevices:
  450.                 DoListSCSIDevices();
  451.                 break;
  452.             case kTestGetDriveInfo:
  453.                 DoGetDriveInfo(gCurrentDevice, FALSE);
  454.                 break;
  455.             case kTestUnitReady:
  456.                 DoTestUnitReady(gCurrentDevice);
  457.                 break;
  458.             case kTestReadBlockZero:
  459.                 DoReadBlockZero(gCurrentDevice);
  460.                 break;
  461.             default:
  462.                 break;
  463.             }
  464.             break;
  465.         case MENU_CurrentBus:
  466.             gCurrentDevice.bus = menuItem - 1;
  467.             gUpdateMenusNeeded = TRUE;
  468.             break;
  469.         case MENU_CurrentTarget:
  470.             gCurrentDevice.targetID = menuItem - 1;
  471.             gUpdateMenusNeeded = TRUE;
  472.             break;
  473.         case MENU_CurrentLUN:
  474.             gCurrentDevice.LUN = menuItem - 1;
  475.             gUpdateMenusNeeded = TRUE;
  476.             break;
  477.         }
  478.         HiliteMenu(0);
  479. }
  480.  
  481. void
  482. SetupEverything()
  483. {
  484.         int                    i;
  485.         
  486.         MaxApplZone();
  487.         InitGraf(&qd.thePort);
  488.         InitFonts();
  489.         InitWindows();
  490.         InitMenus();
  491.         TEInit();
  492.         InitDialogs(NULL);
  493.         for (i = 0; i < 8; i++)
  494.             MoreMasters();
  495.         HNoPurge((Handle) GetCursor(watchCursor));
  496.         SetCursor(*GetCursor(watchCursor));
  497.         SetupMenus();
  498. }
  499.  
  500. void
  501. SetupMenus()
  502. {
  503.         register Handle        menuBarHdl;
  504.  
  505.         /*
  506.          * We ought to do some error checking here.
  507.          */
  508.         menuBarHdl = GetNewMBar(MBAR_MenuBar);
  509.         SetMenuBar(menuBarHdl);
  510.         gAppleMenu = GetMHandle(MENU_Apple);
  511.         AddResMenu(gAppleMenu, 'DRVR');
  512.         gFileMenu = GetMHandle(MENU_File);
  513.         gEditMenu = GetMHandle(MENU_Edit);
  514.         gTestMenu = GetMHandle(MENU_Test);
  515.         gCurrentBusMenu = GetMHandle(MENU_CurrentBus);
  516.         gCurrentTargetMenu = GetMHandle(MENU_CurrentTarget);
  517.         gCurrentLUNMenu = GetMHandle(MENU_CurrentLUN);
  518.         DrawMenuBar();
  519.         gUpdateMenusNeeded = TRUE;
  520. }
  521.  
  522. void
  523. AdjustMenus(void)
  524. {
  525.         short                    i;
  526.         short                    nItems;
  527.         
  528.         EnableItem(gFileMenu, kFileQuit);
  529.         EnableItem(gFileMenu, kFileDebug);
  530.         if (IsOurWindow(FrontWindow())) {
  531.             EnableItem(gFileMenu, kFilePageSetup);
  532.             EnableItem(gFileMenu, kFilePrint);
  533.             EnableItem(gTestMenu, kTestListSCSIDevices);
  534.             EnableItem(gTestMenu, kTestGetDriveInfo);
  535.             EnableItem(gTestMenu, kTestUnitReady);
  536.             EnableItem(gTestMenu, kTestVerboseDisplay);
  537.             CheckItem(gTestMenu, kTestVerboseDisplay, gVerboseDisplay);    
  538.             EnableItem(gTestMenu, kTestEnableAllLogicalUnits);
  539.             CheckItem(gTestMenu, kTestEnableAllLogicalUnits, (gMaxLogicalUnit == 7));
  540.             if (AsyncSCSIPresent()) {
  541.                 EnableItem(gTestMenu, kTestEnableNewManager);
  542.             }
  543.             else {
  544.                 DisableItem(gTestMenu, kTestEnableNewManager);
  545.             }
  546.             if (gEnableNewSCSIManager) {
  547.                 EnableItem(gCurrentBusMenu, 0);
  548.                 EnableItem(gTestMenu, kTestEnableSelectWithATN);
  549.                 EnableItem(gTestMenu, kTestDoDisconnect);
  550.                 EnableItem(gTestMenu, kTestDontDisconnect);
  551.             }
  552.             else {
  553.                 DisableItem(gCurrentBusMenu, 0);
  554.                 DisableItem(gTestMenu, kTestEnableSelectWithATN);
  555.                 DisableItem(gTestMenu, kTestDoDisconnect);
  556.                 DisableItem(gTestMenu, kTestDontDisconnect);
  557.             }
  558.             CheckItem(gTestMenu, kTestEnableNewManager, gEnableNewSCSIManager);
  559.             CheckItem(gTestMenu, kTestEnableSelectWithATN, gEnableSelectWithATN);
  560.             CheckItem(gTestMenu, kTestDoDisconnect, gDoDisconnect);
  561.             CheckItem(gTestMenu, kTestDontDisconnect, gDontDisconnect);
  562.             EnableItem(gTestMenu, kTestEnableAllLogicalUnits);
  563.             CheckItem(gTestMenu, kTestEnableAllLogicalUnits, (gMaxLogicalUnit == 7));
  564.             /* */
  565.             nItems = CountMItems(gCurrentTargetMenu);
  566.             for (i = 1; i <= nItems; i++)
  567.                 CheckItem(gCurrentTargetMenu, i, (gCurrentDevice.targetID == (i - 1)) ? TRUE : FALSE);
  568.             nItems = CountMItems(gCurrentBusMenu);
  569.             for (i = 1; i <= nItems; i++)
  570.                 CheckItem(gCurrentBusMenu, i, (gCurrentDevice.bus == (i - 1)) ? TRUE : FALSE);
  571.             nItems = CountMItems(gCurrentLUNMenu);
  572.             for (i = 1; i <= nItems; i++) {
  573.                 if ((i - 1) <= gMaxLogicalUnit)
  574.                     EnableItem(gCurrentLUNMenu, i);
  575.                 else {
  576.                     DisableItem(gCurrentLUNMenu, i);
  577.                 }
  578.                 CheckItem(gCurrentLUNMenu, i, (gCurrentDevice.LUN == (i - 1)) ? TRUE : FALSE);
  579.             }
  580.             /* */
  581.             if (HasLogFile(gLogListHandle)) {
  582.                 EnableItem(gFileMenu, kFileCloseLogFile);
  583.                 DisableItem(gFileMenu, kFileCreateLogFile);
  584.             }
  585.             else {
  586.                 EnableItem(gFileMenu, kFileCreateLogFile);
  587.                 DisableItem(gFileMenu, kFileCloseLogFile);
  588.             }
  589.         }
  590.         AdjustEditMenu(IsOurWindow(FrontWindow()) == FALSE);
  591. }
  592.  
  593. /*
  594.  * AdjustEditMenu
  595.  * Enable/disable Edit Menu options.
  596.  */
  597. void
  598. AdjustEditMenu(
  599.         Boolean                isDeskAcc
  600.     )
  601. {
  602.         if (isDeskAcc) {
  603.             EnableItem(gEditMenu, kEditUndo);
  604.             EnableItem(gEditMenu, kEditCut);
  605.             EnableItem(gEditMenu, kEditCopy);
  606.             EnableItem(gEditMenu, kEditPaste);
  607.             EnableItem(gEditMenu, kEditClear);
  608.         }
  609.         else {
  610.             DisableItem(gEditMenu, kEditUndo);
  611.             DisableItem(gEditMenu, kEditCut);
  612.             DisableItem(gEditMenu, kEditCopy);
  613.             DisableItem(gEditMenu, kEditPaste);
  614.             DisableItem(gEditMenu, kEditClear);
  615.         }
  616. }
  617.  
  618. void
  619. DoAbout()
  620. {
  621.         GrafPtr                            savePort;
  622.         DialogPtr                        dialog;
  623.         short                            item;
  624.         
  625.         GetPort(&savePort);
  626.         dialog = GetNewDialog(DLOG_About, NULL, (WindowPtr) -1L);
  627.         ShowWindow(dialog);
  628.         SetPort(dialog);
  629.         ModalDialog(NULL, &item);
  630.         DisposDialog(dialog);
  631.         SetPort(savePort);
  632. }
  633.  
  634. void
  635. HexToString(
  636.         unsigned long                    value,
  637.         short                            hexDigits,
  638.         Str255                            result
  639.     )
  640. {
  641.         register unsigned short            digit;
  642.         register char                    *text;
  643.         
  644.         text = (char *) result;
  645.         text[0] = hexDigits;
  646.         for (; hexDigits > 0; --hexDigits) {
  647.             digit = value & 0xF;
  648.             if (digit >= 10)
  649.                 text[hexDigits] = digit - 10 + 'a';
  650.             else {
  651.                 text[hexDigits] = digit + '0';
  652.             }
  653.             value >>= 4;
  654.         }
  655. }
  656.  
  657. Boolean
  658. HexToNum(
  659.         ConstStr255Param                hexString,
  660.         unsigned long                    *result
  661.     )
  662. {
  663.         register short                    i;
  664.         register unsigned short            digit;
  665.         
  666.         *result = 0;
  667.         for (i = 1; i <= hexString[0]; i++) {
  668.             digit = hexString[i];
  669.             if (digit >= '0' && digit <= '9')
  670.                 digit -= '0';
  671.             else if (digit >= 'a' && digit <= 'f')
  672.                 digit = digit - 'a' + 10;
  673.             else if (digit >= 'A' && digit <= 'F')
  674.                 digit = digit - 'A' + 10;
  675.             else {
  676.                 return (FALSE);
  677.             }
  678.             *result <<= 4;
  679.             *result |= digit;
  680.         }
  681.         return (TRUE);
  682. }
  683.  
  684. void
  685. DoPageSetup(void)
  686. {
  687.         PrOpen();
  688.         if (PrError() == noErr) {
  689.             if (gPrintHandle == NULL) {
  690.                 gPrintHandle = (THPrint) NewHandle(sizeof (TPrint));
  691.                 if (gPrintHandle != NULL)
  692.                     PrintDefault(gPrintHandle);
  693.             }
  694.             if (gPrintHandle != NULL)
  695.                 (void) PrStlDialog(gPrintHandle);
  696.             PrClose();
  697.         }
  698. }
  699.  
  700.